{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 基于物品的协同过滤算法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 导入包\n",
    "import random\n",
    "import math\n",
    "import time\n",
    "from tqdm import tqdm"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 一. 通用函数定义"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 定义装饰器，监控运行时间\n",
    "def timmer(func):\n",
    "    def wrapper(*args, **kwargs):\n",
    "        start_time = time.time()\n",
    "        res = func(*args, **kwargs)\n",
    "        stop_time = time.time()\n",
    "        print('Func %s, run time: %s' % (func.__name__, stop_time - start_time))\n",
    "        return res\n",
    "    return wrapper"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1. 数据处理相关\n",
    "1. load data\n",
    "2. split data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Dataset():\n",
    "    \n",
    "    def __init__(self, fp):\n",
    "        # fp: data file path\n",
    "        self.data = self.loadData(fp)\n",
    "    \n",
    "    @timmer\n",
    "    def loadData(self, fp):\n",
    "        data = []\n",
    "        for l in open(fp):\n",
    "            data.append(tuple(map(int, l.strip().split('::')[:2])))\n",
    "        return data\n",
    "    \n",
    "    @timmer\n",
    "    def splitData(self, M, k, seed=1):\n",
    "        '''\n",
    "        :params: data, 加载的所有(user, item)数据条目\n",
    "        :params: M, 划分的数目，最后需要取M折的平均\n",
    "        :params: k, 本次是第几次划分，k~[0, M)\n",
    "        :params: seed, random的种子数，对于不同的k应设置成一样的\n",
    "        :return: train, test\n",
    "        '''\n",
    "        train, test = [], []\n",
    "        random.seed(seed)\n",
    "        for user, item in self.data:\n",
    "            # 这里与书中的不一致，本人认为取M-1较为合理，因randint是左右都覆盖的\n",
    "            if random.randint(0, M-1) == k:  \n",
    "                test.append((user, item))\n",
    "            else:\n",
    "                train.append((user, item))\n",
    "\n",
    "        # 处理成字典的形式，user->set(items)\n",
    "        def convert_dict(data):\n",
    "            data_dict = {}\n",
    "            for user, item in data:\n",
    "                if user not in data_dict:\n",
    "                    data_dict[user] = set()\n",
    "                data_dict[user].add(item)\n",
    "            data_dict = {k: list(data_dict[k]) for k in data_dict}\n",
    "            return data_dict\n",
    "\n",
    "        return convert_dict(train), convert_dict(test)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2. 评价指标\n",
    "1. Precision\n",
    "2. Recall\n",
    "3. Coverage\n",
    "4. Popularity(Novelty)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Metric():\n",
    "    \n",
    "    def __init__(self, train, test, GetRecommendation):\n",
    "        '''\n",
    "        :params: train, 训练数据\n",
    "        :params: test, 测试数据\n",
    "        :params: GetRecommendation, 为某个用户获取推荐物品的接口函数\n",
    "        '''\n",
    "        self.train = train\n",
    "        self.test = test\n",
    "        self.GetRecommendation = GetRecommendation\n",
    "        self.recs = self.getRec()\n",
    "        \n",
    "    # 为test中的每个用户进行推荐\n",
    "    def getRec(self):\n",
    "        recs = {}\n",
    "        for user in self.test:\n",
    "            rank = self.GetRecommendation(user)\n",
    "            recs[user] = rank\n",
    "        return recs\n",
    "        \n",
    "    # 定义精确率指标计算方式\n",
    "    def precision(self):\n",
    "        all, hit = 0, 0\n",
    "        for user in self.test:\n",
    "            test_items = set(self.test[user])\n",
    "            rank = self.recs[user]\n",
    "            for item, score in rank:\n",
    "                if item in test_items:\n",
    "                    hit += 1\n",
    "            all += len(rank)\n",
    "        return round(hit / all * 100, 2)\n",
    "    \n",
    "    # 定义召回率指标计算方式\n",
    "    def recall(self):\n",
    "        all, hit = 0, 0\n",
    "        for user in self.test:\n",
    "            test_items = set(self.test[user])\n",
    "            rank = self.recs[user]\n",
    "            for item, score in rank:\n",
    "                if item in test_items:\n",
    "                    hit += 1\n",
    "            all += len(test_items)\n",
    "        return round(hit / all * 100, 2)\n",
    "    \n",
    "    # 定义覆盖率指标计算方式\n",
    "    def coverage(self):\n",
    "        all_item, recom_item = set(), set()\n",
    "        for user in self.test:\n",
    "            for item in self.train[user]:\n",
    "                all_item.add(item)\n",
    "            rank = self.recs[user]\n",
    "            for item, score in rank:\n",
    "                recom_item.add(item)\n",
    "        return round(len(recom_item) / len(all_item) * 100, 2)\n",
    "    \n",
    "    # 定义新颖度指标计算方式\n",
    "    def popularity(self):\n",
    "        # 计算物品的流行度\n",
    "        item_pop = {}\n",
    "        for user in self.train:\n",
    "            for item in self.train[user]:\n",
    "                if item not in item_pop:\n",
    "                    item_pop[item] = 0\n",
    "                item_pop[item] += 1\n",
    "\n",
    "        num, pop = 0, 0\n",
    "        for user in self.test:\n",
    "            rank = self.recs[user]\n",
    "            for item, score in rank:\n",
    "                # 取对数，防止因长尾问题带来的被流行物品所主导\n",
    "                pop += math.log(1 + item_pop[item])\n",
    "                num += 1\n",
    "        return round(pop / num, 6)\n",
    "    \n",
    "    def eval(self):\n",
    "        metric = {'Precision': self.precision(),\n",
    "                  'Recall': self.recall(),\n",
    "                  'Coverage': self.coverage(),\n",
    "                  'Popularity': self.popularity()}\n",
    "        print('Metric:', metric)\n",
    "        return metric"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 二. 算法实现\n",
    "1. ItemCF\n",
    "2. ItemIUF\n",
    "3. ItemCF_Norm"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 1. 基于物品余弦相似度的推荐\n",
    "def ItemCF(train, K, N):\n",
    "    '''\n",
    "    :params: train, 训练数据集\n",
    "    :params: K, 超参数，设置取TopK相似物品数目\n",
    "    :params: N, 超参数，设置取TopN推荐物品数目\n",
    "    :return: GetRecommendation, 推荐接口函数\n",
    "    '''\n",
    "    # 计算物品相似度矩阵\n",
    "    sim = {}\n",
    "    num = {}\n",
    "    for user in train:\n",
    "        items = train[user]\n",
    "        for i in range(len(items)):\n",
    "            u = items[i]\n",
    "            if u not in num:\n",
    "                num[u] = 0\n",
    "            num[u] += 1\n",
    "            if u not in sim:\n",
    "                sim[u] = {}\n",
    "            for j in range(len(items)):\n",
    "                if j == i: continue\n",
    "                v = items[j]\n",
    "                if v not in sim[u]:\n",
    "                    sim[u][v] = 0\n",
    "                sim[u][v] += 1\n",
    "    for u in sim:\n",
    "        for v in sim[u]:\n",
    "            sim[u][v] /= math.sqrt(num[u] * num[v])\n",
    "    \n",
    "    # 按照相似度排序\n",
    "    sorted_item_sim = {k: list(sorted(v.items(), \\\n",
    "                               key=lambda x: x[1], reverse=True)) \\\n",
    "                       for k, v in sim.items()}\n",
    "    \n",
    "    # 获取接口函数\n",
    "    def GetRecommendation(user):\n",
    "        items = {}\n",
    "        seen_items = set(train[user])\n",
    "        for item in train[user]:\n",
    "            for u, _ in sorted_item_sim[item][:K]:\n",
    "                if u not in seen_items:\n",
    "                    if u not in items:\n",
    "                        items[u] = 0\n",
    "                    items[u] += sim[item][u]\n",
    "        recs = list(sorted(items.items(), key=lambda x: x[1], reverse=True))[:N]\n",
    "        return recs\n",
    "    \n",
    "    return GetRecommendation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 2. 基于改进的物品余弦相似度的推荐\n",
    "def ItemIUF(train, K, N):\n",
    "    '''\n",
    "    :params: train, 训练数据集\n",
    "    :params: K, 超参数，设置取TopK相似物品数目\n",
    "    :params: N, 超参数，设置取TopN推荐物品数目\n",
    "    :return: GetRecommendation, 推荐接口函数\n",
    "    ''' \n",
    "    # 计算物品相似度矩阵\n",
    "    sim = {}\n",
    "    num = {}\n",
    "    for user in train:\n",
    "        items = train[user]\n",
    "        for i in range(len(items)):\n",
    "            u = items[i]\n",
    "            if u not in num:\n",
    "                num[u] = 0\n",
    "            num[u] += 1\n",
    "            if u not in sim:\n",
    "                sim[u] = {}\n",
    "            for j in range(len(items)):\n",
    "                if j == i: continue\n",
    "                v = items[j]\n",
    "                if v not in sim[u]:\n",
    "                    sim[u][v] = 0\n",
    "                # 相比ItemCF，主要是改进了这里\n",
    "                sim[u][v] += 1 / math.log(1 + len(items))\n",
    "    for u in sim:\n",
    "        for v in sim[u]:\n",
    "            sim[u][v] /= math.sqrt(num[u] * num[v])\n",
    "    \n",
    "    # 按照相似度排序\n",
    "    sorted_item_sim = {k: list(sorted(v.items(), \\\n",
    "                               key=lambda x: x[1], reverse=True)) \\\n",
    "                       for k, v in sim.items()}\n",
    "    \n",
    "    # 获取接口函数\n",
    "    def GetRecommendation(user):\n",
    "        items = {}\n",
    "        seen_items = set(train[user])\n",
    "        for item in train[user]:\n",
    "            for u, _ in sorted_item_sim[item][:K]:\n",
    "                # 要去掉用户见过的\n",
    "                if u not in seen_items:\n",
    "                    if u not in items:\n",
    "                        items[u] = 0\n",
    "                    items[u] += sim[item][u]\n",
    "        recs = list(sorted(items.items(), key=lambda x: x[1], reverse=True))[:N]\n",
    "        return recs\n",
    "    \n",
    "    return GetRecommendation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 3. 基于归一化的物品余弦相似度的推荐\n",
    "def ItemCF_Norm(train, K, N):\n",
    "    '''\n",
    "    :params: train, 训练数据集\n",
    "    :params: K, 超参数，设置取TopK相似物品数目\n",
    "    :params: N, 超参数，设置取TopN推荐物品数目\n",
    "    :return: GetRecommendation, 推荐接口函数\n",
    "    '''\n",
    "    # 计算物品相似度矩阵\n",
    "    sim = {}\n",
    "    num = {}\n",
    "    for user in train:\n",
    "        items = train[user]\n",
    "        for i in range(len(items)):\n",
    "            u = items[i]\n",
    "            if u not in num:\n",
    "                num[u] = 0\n",
    "            num[u] += 1\n",
    "            if u not in sim:\n",
    "                sim[u] = {}\n",
    "            for j in range(len(items)):\n",
    "                if j == i: continue\n",
    "                v = items[j]\n",
    "                if v not in sim[u]:\n",
    "                    sim[u][v] = 0\n",
    "                sim[u][v] += 1\n",
    "    for u in sim:\n",
    "        for v in sim[u]:\n",
    "            sim[u][v] /= math.sqrt(num[u] * num[v])\n",
    "            \n",
    "    # 对相似度矩阵进行按行归一化\n",
    "    for u in sim:\n",
    "        s = 0\n",
    "        for v in sim[u]:\n",
    "            s += sim[u][v]\n",
    "        if s > 0:\n",
    "            for v in sim[u]:\n",
    "                sim[u][v] /= s\n",
    "    \n",
    "    # 按照相似度排序\n",
    "    sorted_item_sim = {k: list(sorted(v.items(), \\\n",
    "                               key=lambda x: x[1], reverse=True)) \\\n",
    "                       for k, v in sim.items()}\n",
    "    \n",
    "    # 获取接口函数\n",
    "    def GetRecommendation(user):\n",
    "        items = {}\n",
    "        seen_items = set(train[user])\n",
    "        for item in train[user]:\n",
    "            for u, _ in sorted_item_sim[item][:K]:\n",
    "                if u not in seen_items:\n",
    "                    if u not in items:\n",
    "                        items[u] = 0\n",
    "                    items[u] += sim[item][u]\n",
    "        recs = list(sorted(items.items(), key=lambda x: x[1], reverse=True))[:N]\n",
    "        return recs\n",
    "    \n",
    "    return GetRecommendation"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 三. 实验\n",
    "1. ItemCF实验，K=[5, 10, 20, 40, 80, 160]\n",
    "2. ItemIUF实验, K=10\n",
    "3. ItemCF-Norm实验，K=10\n",
    "\n",
    "M=8, N=10"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Experiment():\n",
    "    \n",
    "    def __init__(self, M, K, N, fp='../dataset/ml-1m/ratings.dat', rt='ItemCF'):\n",
    "        '''\n",
    "        :params: M, 进行多少次实验\n",
    "        :params: K, TopK相似物品的个数\n",
    "        :params: N, TopN推荐物品的个数\n",
    "        :params: fp, 数据文件路径\n",
    "        :params: rt, 推荐算法类型\n",
    "        '''\n",
    "        self.M = M\n",
    "        self.K = K\n",
    "        self.N = N\n",
    "        self.fp = fp\n",
    "        self.rt = rt\n",
    "        self.alg = {'ItemCF': ItemCF, 'ItemIUF': ItemIUF, 'ItemCF-Norm': ItemCF_Norm}\n",
    "    \n",
    "    # 定义单次实验\n",
    "    @timmer\n",
    "    def worker(self, train, test):\n",
    "        '''\n",
    "        :params: train, 训练数据集\n",
    "        :params: test, 测试数据集\n",
    "        :return: 各指标的值\n",
    "        '''\n",
    "        getRecommendation = self.alg[self.rt](train, self.K, self.N)\n",
    "        metric = Metric(train, test, getRecommendation)\n",
    "        return metric.eval()\n",
    "    \n",
    "    # 多次实验取平均\n",
    "    @timmer\n",
    "    def run(self):\n",
    "        metrics = {'Precision': 0, 'Recall': 0, \n",
    "                   'Coverage': 0, 'Popularity': 0}\n",
    "        dataset = Dataset(self.fp)\n",
    "        for ii in range(self.M):\n",
    "            train, test = dataset.splitData(self.M, ii)\n",
    "            print('Experiment {}:'.format(ii))\n",
    "            metric = self.worker(train, test)\n",
    "            metrics = {k: metrics[k]+metric[k] for k in metrics}\n",
    "        metrics = {k: metrics[k] / self.M for k in metrics}\n",
    "        print('Average Result (M={}, K={}, N={}): {}'.format(\\\n",
    "                              self.M, self.K, self.N, metrics))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "collapsed": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Func loadData, run time: 1.357867956161499\n",
      "Func splitData, run time: 1.9750580787658691\n",
      "Experiment 0:\n",
      "Metric: {'Precision': 21.29, 'Recall': 10.22, 'Coverage': 21.3, 'Popularity': 7.167103}\n",
      "Func worker, run time: 105.31731390953064\n",
      "Func splitData, run time: 1.8287019729614258\n",
      "Experiment 1:\n",
      "Metric: {'Precision': 21.45, 'Recall': 10.27, 'Coverage': 21.85, 'Popularity': 7.151314}\n",
      "Func worker, run time: 103.2586419582367\n",
      "Func splitData, run time: 1.8108947277069092\n",
      "Experiment 2:\n",
      "Metric: {'Precision': 21.3, 'Recall': 10.18, 'Coverage': 22.03, 'Popularity': 7.165002}\n",
      "Func worker, run time: 101.99979496002197\n",
      "Func splitData, run time: 1.7960660457611084\n",
      "Experiment 3:\n",
      "Metric: {'Precision': 21.17, 'Recall': 10.18, 'Coverage': 21.34, 'Popularity': 7.178365}\n",
      "Func worker, run time: 102.11498403549194\n",
      "Func splitData, run time: 1.7130441665649414\n",
      "Experiment 4:\n",
      "Metric: {'Precision': 21.21, 'Recall': 10.2, 'Coverage': 21.8, 'Popularity': 7.170794}\n",
      "Func worker, run time: 101.90551114082336\n",
      "Func splitData, run time: 1.8183128833770752\n",
      "Experiment 5:\n",
      "Metric: {'Precision': 21.39, 'Recall': 10.32, 'Coverage': 21.76, 'Popularity': 7.163104}\n",
      "Func worker, run time: 101.97199416160583\n",
      "Func splitData, run time: 1.7958929538726807\n",
      "Experiment 6:\n",
      "Metric: {'Precision': 21.31, 'Recall': 10.25, 'Coverage': 21.9, 'Popularity': 7.161708}\n",
      "Func worker, run time: 101.57879590988159\n",
      "Func splitData, run time: 1.817734956741333\n",
      "Experiment 7:\n",
      "Metric: {'Precision': 21.16, 'Recall': 10.15, 'Coverage': 21.38, 'Popularity': 7.175929}\n",
      "Func worker, run time: 101.03642511367798\n",
      "Average Result (M=8, K=5, N=10): {'Precision': 21.284999999999997, 'Recall': 10.221250000000001, 'Coverage': 21.67, 'Popularity': 7.166664874999999}\n",
      "Func run, run time: 835.2748167514801\n",
      "Func loadData, run time: 1.2348299026489258\n",
      "Func splitData, run time: 1.8201029300689697\n",
      "Experiment 0:\n",
      "Metric: {'Precision': 22.01, 'Recall': 10.57, 'Coverage': 19.35, 'Popularity': 7.248504}\n",
      "Func worker, run time: 104.0655460357666\n",
      "Func splitData, run time: 1.8287677764892578\n",
      "Experiment 1:\n",
      "Metric: {'Precision': 22.12, 'Recall': 10.59, 'Coverage': 18.95, 'Popularity': 7.244242}\n",
      "Func worker, run time: 103.43892693519592\n",
      "Func splitData, run time: 1.804075002670288\n",
      "Experiment 2:\n",
      "Metric: {'Precision': 22.59, 'Recall': 10.8, 'Coverage': 19.19, 'Popularity': 7.245515}\n",
      "Func worker, run time: 103.44988584518433\n",
      "Func splitData, run time: 1.7733349800109863\n",
      "Experiment 3:\n",
      "Metric: {'Precision': 22.02, 'Recall': 10.58, 'Coverage': 19.37, 'Popularity': 7.245227}\n",
      "Func worker, run time: 104.05003190040588\n",
      "Func splitData, run time: 1.8094689846038818\n",
      "Experiment 4:\n",
      "Metric: {'Precision': 22.11, 'Recall': 10.63, 'Coverage': 19.33, 'Popularity': 7.260709}\n",
      "Func worker, run time: 100.68873810768127\n",
      "Func splitData, run time: 1.7294957637786865\n",
      "Experiment 5:\n",
      "Metric: {'Precision': 22.17, 'Recall': 10.69, 'Coverage': 19.02, 'Popularity': 7.251251}\n",
      "Func worker, run time: 101.01811790466309\n",
      "Func splitData, run time: 1.73459792137146\n",
      "Experiment 6:\n",
      "Metric: {'Precision': 22.4, 'Recall': 10.77, 'Coverage': 18.48, 'Popularity': 7.24112}\n",
      "Func worker, run time: 101.37971901893616\n",
      "Func splitData, run time: 1.7321960926055908\n",
      "Experiment 7:\n",
      "Metric: {'Precision': 21.98, 'Recall': 10.54, 'Coverage': 19.18, 'Popularity': 7.259772}\n",
      "Func worker, run time: 101.52781391143799\n",
      "Average Result (M=8, K=10, N=10): {'Precision': 22.174999999999997, 'Recall': 10.646249999999998, 'Coverage': 19.10875, 'Popularity': 7.2495425}\n",
      "Func run, run time: 835.2476677894592\n",
      "Func loadData, run time: 1.2376840114593506\n",
      "Func splitData, run time: 1.7310190200805664\n",
      "Experiment 0:\n",
      "Metric: {'Precision': 22.09, 'Recall': 10.61, 'Coverage': 16.78, 'Popularity': 7.331556}\n",
      "Func worker, run time: 104.41120624542236\n",
      "Func splitData, run time: 1.7812540531158447\n",
      "Experiment 1:\n",
      "Metric: {'Precision': 22.41, 'Recall': 10.73, 'Coverage': 16.87, 'Popularity': 7.327797}\n",
      "Func worker, run time: 104.20949697494507\n",
      "Func splitData, run time: 1.7324512004852295\n",
      "Experiment 2:\n",
      "Metric: {'Precision': 22.5, 'Recall': 10.76, 'Coverage': 16.83, 'Popularity': 7.330741}\n",
      "Func worker, run time: 104.43356919288635\n",
      "Func splitData, run time: 1.7455089092254639\n",
      "Experiment 3:\n",
      "Metric: {'Precision': 21.99, 'Recall': 10.57, 'Coverage': 17.12, 'Popularity': 7.339063}\n",
      "Func worker, run time: 103.83610510826111\n",
      "Func splitData, run time: 1.7279980182647705\n",
      "Experiment 4:\n",
      "Metric: {'Precision': 21.84, 'Recall': 10.5, 'Coverage': 16.99, 'Popularity': 7.340118}\n",
      "Func worker, run time: 104.33192300796509\n",
      "Func splitData, run time: 1.6494619846343994\n",
      "Experiment 5:\n",
      "Metric: {'Precision': 21.86, 'Recall': 10.54, 'Coverage': 16.85, 'Popularity': 7.3356}\n",
      "Func worker, run time: 109.94820308685303\n",
      "Func splitData, run time: 1.9003541469573975\n",
      "Experiment 6:\n",
      "Metric: {'Precision': 22.37, 'Recall': 10.75, 'Coverage': 16.8, 'Popularity': 7.321315}\n",
      "Func worker, run time: 111.54657578468323\n",
      "Func splitData, run time: 1.8000450134277344\n",
      "Experiment 7:\n",
      "Metric: {'Precision': 21.94, 'Recall': 10.52, 'Coverage': 17.12, 'Popularity': 7.351119}\n",
      "Func worker, run time: 108.88186001777649\n",
      "Average Result (M=8, K=20, N=10): {'Precision': 22.125, 'Recall': 10.6225, 'Coverage': 16.919999999999998, 'Popularity': 7.334663624999999}\n",
      "Func run, run time: 867.068473815918\n",
      "Func loadData, run time: 1.2636096477508545\n",
      "Func splitData, run time: 1.806412935256958\n",
      "Experiment 0:\n",
      "Metric: {'Precision': 21.54, 'Recall': 10.34, 'Coverage': 15.47, 'Popularity': 7.389295}\n",
      "Func worker, run time: 114.59086179733276\n",
      "Func splitData, run time: 1.8383910655975342\n",
      "Experiment 1:\n",
      "Metric: {'Precision': 22.08, 'Recall': 10.57, 'Coverage': 15.48, 'Popularity': 7.382177}\n",
      "Func worker, run time: 113.1404218673706\n",
      "Func splitData, run time: 1.806563138961792\n",
      "Experiment 2:\n",
      "Metric: {'Precision': 21.78, 'Recall': 10.41, 'Coverage': 15.07, 'Popularity': 7.382617}\n",
      "Func worker, run time: 113.9739158153534\n",
      "Func splitData, run time: 1.768733263015747\n",
      "Experiment 3:\n",
      "Metric: {'Precision': 21.47, 'Recall': 10.32, 'Coverage': 15.71, 'Popularity': 7.393157}\n",
      "Func worker, run time: 117.33210301399231\n",
      "Func splitData, run time: 1.9012501239776611\n",
      "Experiment 4:\n",
      "Metric: {'Precision': 21.24, 'Recall': 10.21, 'Coverage': 15.74, 'Popularity': 7.397843}\n",
      "Func worker, run time: 120.33364200592041\n",
      "Func splitData, run time: 1.9740369319915771\n",
      "Experiment 5:\n",
      "Metric: {'Precision': 21.12, 'Recall': 10.19, 'Coverage': 15.63, 'Popularity': 7.385106}\n",
      "Func worker, run time: 124.77882289886475\n",
      "Func splitData, run time: 1.9539570808410645\n",
      "Experiment 6:\n",
      "Metric: {'Precision': 21.7, 'Recall': 10.43, 'Coverage': 15.56, 'Popularity': 7.378948}\n",
      "Func worker, run time: 124.54463386535645\n",
      "Func splitData, run time: 1.9221651554107666\n",
      "Experiment 7:\n",
      "Metric: {'Precision': 21.28, 'Recall': 10.21, 'Coverage': 15.23, 'Popularity': 7.404669}\n",
      "Func worker, run time: 124.96897101402283\n",
      "Average Result (M=8, K=40, N=10): {'Precision': 21.526249999999997, 'Recall': 10.335, 'Coverage': 15.48625, 'Popularity': 7.3892265}\n",
      "Func run, run time: 970.096118927002\n",
      "Func loadData, run time: 1.2885360717773438\n",
      "Func splitData, run time: 1.9453051090240479\n",
      "Experiment 0:\n",
      "Metric: {'Precision': 20.71, 'Recall': 9.95, 'Coverage': 13.71, 'Popularity': 7.41184}\n",
      "Func worker, run time: 136.20149898529053\n",
      "Func splitData, run time: 1.9885108470916748\n",
      "Experiment 1:\n",
      "Metric: {'Precision': 21.06, 'Recall': 10.08, 'Coverage': 13.64, 'Popularity': 7.399879}\n",
      "Func worker, run time: 138.96288514137268\n",
      "Func splitData, run time: 1.9737217426300049\n",
      "Experiment 2:\n",
      "Metric: {'Precision': 20.69, 'Recall': 9.89, 'Coverage': 13.18, 'Popularity': 7.405965}\n",
      "Func worker, run time: 140.04792022705078\n",
      "Func splitData, run time: 1.9420268535614014\n",
      "Experiment 3:\n",
      "Metric: {'Precision': 20.69, 'Recall': 9.94, 'Coverage': 13.81, 'Popularity': 7.414836}\n",
      "Func worker, run time: 134.16970086097717\n",
      "Func splitData, run time: 1.8937797546386719\n",
      "Experiment 4:\n",
      "Metric: {'Precision': 20.53, 'Recall': 9.87, 'Coverage': 13.84, 'Popularity': 7.416375}\n",
      "Func worker, run time: 133.87962293624878\n",
      "Func splitData, run time: 1.9022479057312012\n",
      "Experiment 5:\n",
      "Metric: {'Precision': 20.36, 'Recall': 9.82, 'Coverage': 13.57, 'Popularity': 7.411035}\n",
      "Func worker, run time: 134.15448117256165\n",
      "Func splitData, run time: 1.8966238498687744\n",
      "Experiment 6:\n",
      "Metric: {'Precision': 20.79, 'Recall': 9.99, 'Coverage': 13.5, 'Popularity': 7.40158}\n",
      "Func worker, run time: 130.25284504890442\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Func splitData, run time: 1.8891630172729492\n",
      "Experiment 7:\n",
      "Metric: {'Precision': 20.46, 'Recall': 9.81, 'Coverage': 14.06, 'Popularity': 7.422915}\n",
      "Func worker, run time: 128.92854809761047\n",
      "Average Result (M=8, K=80, N=10): {'Precision': 20.66125, 'Recall': 9.91875, 'Coverage': 13.66375, 'Popularity': 7.410553125}\n",
      "Func run, run time: 1093.511596918106\n",
      "Func loadData, run time: 1.2567250728607178\n",
      "Func splitData, run time: 1.8248507976531982\n",
      "Experiment 0:\n",
      "Metric: {'Precision': 19.56, 'Recall': 9.4, 'Coverage': 11.92, 'Popularity': 7.386144}\n",
      "Func worker, run time: 151.13417983055115\n",
      "Func splitData, run time: 1.8845288753509521\n",
      "Experiment 1:\n",
      "Metric: {'Precision': 19.76, 'Recall': 9.46, 'Coverage': 12.5, 'Popularity': 7.368402}\n",
      "Func worker, run time: 153.7669289112091\n",
      "Func splitData, run time: 2.0910489559173584\n",
      "Experiment 2:\n",
      "Metric: {'Precision': 19.68, 'Recall': 9.41, 'Coverage': 11.96, 'Popularity': 7.379513}\n",
      "Func worker, run time: 164.56706523895264\n",
      "Func splitData, run time: 1.9786031246185303\n",
      "Experiment 3:\n",
      "Metric: {'Precision': 19.4, 'Recall': 9.32, 'Coverage': 12.08, 'Popularity': 7.389774}\n",
      "Func worker, run time: 164.01787090301514\n",
      "Func splitData, run time: 2.0074920654296875\n",
      "Experiment 4:\n",
      "Metric: {'Precision': 19.26, 'Recall': 9.26, 'Coverage': 12.21, 'Popularity': 7.385536}\n",
      "Func worker, run time: 163.91729307174683\n",
      "Func splitData, run time: 1.9719181060791016\n",
      "Experiment 5:\n",
      "Metric: {'Precision': 19.06, 'Recall': 9.19, 'Coverage': 12.22, 'Popularity': 7.379692}\n",
      "Func worker, run time: 165.07782125473022\n",
      "Func splitData, run time: 1.930976152420044\n",
      "Experiment 6:\n",
      "Metric: {'Precision': 19.25, 'Recall': 9.25, 'Coverage': 11.95, 'Popularity': 7.374345}\n",
      "Func worker, run time: 163.38418984413147\n",
      "Func splitData, run time: 1.8265297412872314\n",
      "Experiment 7:\n",
      "Metric: {'Precision': 19.35, 'Recall': 9.28, 'Coverage': 11.87, 'Popularity': 7.401496}\n",
      "Func worker, run time: 156.3625569343567\n",
      "Average Result (M=8, K=160, N=10): {'Precision': 19.415000000000003, 'Recall': 9.32125, 'Coverage': 12.088750000000001, 'Popularity': 7.38311275}\n",
      "Func run, run time: 1299.2117609977722\n"
     ]
    }
   ],
   "source": [
    "# 1. ItemCF实验\n",
    "M, N = 8, 10\n",
    "for K in [5, 10, 20, 40, 80, 160]:\n",
    "    cf_exp = Experiment(M, K, N, rt='ItemCF')\n",
    "    cf_exp.run()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Func loadData, run time: 1.3564789295196533\n",
      "Func splitData, run time: 1.8902332782745361\n",
      "Experiment 0:\n",
      "Metric: {'Precision': 22.51, 'Recall': 10.81, 'Coverage': 17.53, 'Popularity': 7.346247}\n",
      "Func worker, run time: 202.80446100234985\n",
      "Func splitData, run time: 1.8700988292694092\n",
      "Experiment 1:\n",
      "Metric: {'Precision': 22.87, 'Recall': 10.95, 'Coverage': 17.43, 'Popularity': 7.346612}\n",
      "Func worker, run time: 202.73692202568054\n",
      "Func splitData, run time: 1.9114680290222168\n",
      "Experiment 2:\n",
      "Metric: {'Precision': 22.93, 'Recall': 10.96, 'Coverage': 17.86, 'Popularity': 7.353326}\n",
      "Func worker, run time: 202.54596090316772\n",
      "Func splitData, run time: 1.898630142211914\n",
      "Experiment 3:\n",
      "Metric: {'Precision': 22.5, 'Recall': 10.82, 'Coverage': 17.55, 'Popularity': 7.347087}\n",
      "Func worker, run time: 210.07687187194824\n",
      "Func splitData, run time: 2.0206642150878906\n",
      "Experiment 4:\n",
      "Metric: {'Precision': 22.23, 'Recall': 10.69, 'Coverage': 17.62, 'Popularity': 7.355618}\n",
      "Func worker, run time: 194.73034501075745\n",
      "Func splitData, run time: 1.8169701099395752\n",
      "Experiment 5:\n",
      "Metric: {'Precision': 22.73, 'Recall': 10.96, 'Coverage': 17.45, 'Popularity': 7.351502}\n",
      "Func worker, run time: 191.2959520816803\n",
      "Func splitData, run time: 1.7530040740966797\n",
      "Experiment 6:\n",
      "Metric: {'Precision': 22.92, 'Recall': 11.02, 'Coverage': 17.21, 'Popularity': 7.341635}\n",
      "Func worker, run time: 189.27422094345093\n",
      "Func splitData, run time: 1.7417218685150146\n",
      "Experiment 7:\n",
      "Metric: {'Precision': 22.42, 'Recall': 10.75, 'Coverage': 17.72, 'Popularity': 7.360763}\n",
      "Func worker, run time: 196.7241768836975\n",
      "Average Result (M=8, K=10, N=10): {'Precision': 22.63875, 'Recall': 10.87, 'Coverage': 17.54625, 'Popularity': 7.350348749999999}\n",
      "Func run, run time: 1606.6134660243988\n"
     ]
    }
   ],
   "source": [
    "# 2. ItemIUF实验\n",
    "M, N = 8, 10\n",
    "K = 10 # 与书中保持一致\n",
    "iuf_exp = Experiment(M, K, N, rt='ItemIUF')\n",
    "iuf_exp.run()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Func loadData, run time: 1.2446231842041016\n",
      "Func splitData, run time: 1.8000209331512451\n",
      "Experiment 0:\n",
      "Metric: {'Precision': 22.43, 'Recall': 10.77, 'Coverage': 37.4, 'Popularity': 6.997795}\n",
      "Func worker, run time: 106.30902194976807\n",
      "Func splitData, run time: 1.8364269733428955\n",
      "Experiment 1:\n",
      "Metric: {'Precision': 22.64, 'Recall': 10.84, 'Coverage': 37.74, 'Popularity': 6.993843}\n",
      "Func worker, run time: 105.63388681411743\n",
      "Func splitData, run time: 1.820976972579956\n",
      "Experiment 2:\n",
      "Metric: {'Precision': 23.06, 'Recall': 11.03, 'Coverage': 37.05, 'Popularity': 6.994036}\n",
      "Func worker, run time: 108.06170320510864\n",
      "Func splitData, run time: 1.9166691303253174\n",
      "Experiment 3:\n",
      "Metric: {'Precision': 22.52, 'Recall': 10.82, 'Coverage': 38.16, 'Popularity': 7.003088}\n",
      "Func worker, run time: 112.67198371887207\n",
      "Func splitData, run time: 1.895146131515503\n",
      "Experiment 4:\n",
      "Metric: {'Precision': 22.56, 'Recall': 10.85, 'Coverage': 38.82, 'Popularity': 7.001239}\n",
      "Func worker, run time: 107.44453597068787\n",
      "Func splitData, run time: 1.7972638607025146\n",
      "Experiment 5:\n",
      "Metric: {'Precision': 22.74, 'Recall': 10.97, 'Coverage': 37.12, 'Popularity': 7.007333}\n",
      "Func worker, run time: 106.20418381690979\n",
      "Func splitData, run time: 1.7266900539398193\n",
      "Experiment 6:\n",
      "Metric: {'Precision': 22.82, 'Recall': 10.97, 'Coverage': 37.7, 'Popularity': 6.989135}\n",
      "Func worker, run time: 106.62335729598999\n",
      "Func splitData, run time: 1.8284211158752441\n",
      "Experiment 7:\n",
      "Metric: {'Precision': 22.49, 'Recall': 10.79, 'Coverage': 37.47, 'Popularity': 7.009879}\n",
      "Func worker, run time: 106.70008587837219\n",
      "Average Result (M=8, K=10, N=10): {'Precision': 22.6575, 'Recall': 10.879999999999999, 'Coverage': 37.682500000000005, 'Popularity': 6.9995435}\n",
      "Func run, run time: 875.6982419490814\n"
     ]
    }
   ],
   "source": [
    "# 3. ItemCF-Norm实验\n",
    "M, N = 8, 10\n",
    "K = 10 # 与书中保持一致\n",
    "norm_exp = Experiment(M, K, N, rt='ItemCF-Norm')\n",
    "norm_exp.run()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 四. 实验结果\n",
    "\n",
    "1. ItemCF实验\n",
    "\n",
    "    Running time: 835.2748167514801\n",
    "    \n",
    "    Average Result (M=8, K=5, N=10): \n",
    "    {'Precision': 21.28, 'Recall': 10.22, \n",
    "     'Coverage': 21.67, 'Popularity': 7.16666}\n",
    "     \n",
    "    Running time: 835.2476677894592\n",
    "    \n",
    "    Average Result (M=8, K=10, N=10): \n",
    "    {'Precision': 22.17, 'Recall': 10.65, \n",
    "     'Coverage': 19.11, 'Popularity': 7.2495425}\n",
    "     \n",
    "    Running time: 867.068473815918\n",
    "    \n",
    "    Average Result (M=8, K=20, N=10): \n",
    "    {'Precision': 22.13, 'Recall': 10.62, \n",
    "     'Coverage': 16.92, 'Popularity': 7.33466}\n",
    "     \n",
    "    Running time: 970.096118927002\n",
    "    \n",
    "    Average Result (M=8, K=40, N=10): \n",
    "    {'Precision': 21.53, 'Recall': 10.34, \n",
    "     'Coverage': 15.49, 'Popularity': 7.3892265}\n",
    "     \n",
    "    Running time: 1093.511596918106\n",
    "    \n",
    "    Average Result (M=8, K=80, N=10): \n",
    "    {'Precision': 20.66, 'Recall': 9.92, \n",
    "     'Coverage': 13.66, 'Popularity': 7.41055}\n",
    "     \n",
    "    Running time: 1299.2117609977722\n",
    "    \n",
    "    Average Result (M=8, K=160, N=10): \n",
    "    {'Precision': 19.42, 'Recall': 9.32, \n",
    "     'Coverage': 12.09, 'Popularity': 7.38311}\n",
    "     \n",
    "2. ItemIUF实验\n",
    "    \n",
    "    Running time: 1606.6134660243988\n",
    "    \n",
    "    Average Result (M=8, K=10, N=10): \n",
    "    {'Precision': 22.64, 'Recall': 10.87, \n",
    "     'Coverage': 17.55, 'Popularity': 7.35}\n",
    "     \n",
    "3. ItemCF-Norm实验\n",
    "    \n",
    "    Running time: 875.6982419490814\n",
    "    \n",
    "    Average Result (M=8, K=10, N=10): \n",
    "    {'Precision': 22.66, 'Recall': 10.88, \n",
    "     'Coverage': 37.68, 'Popularity': 6.999544}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 五. 总结\n",
    "1. 数据集分割的小技巧，用同样的seed\n",
    "2. 各个指标的实现，要注意\n",
    "3. 为每个用户推荐的时候是推荐他们**没有见过**的，因为测试集里面是这样的\n",
    "4. 推荐的时候K和N各代表什么意思，要分开设置，先取TopK，然后取TopN\n",
    "5. ItemIUF的结果与书中的正好相反，书里面是PR都有些许降低，但CP有提升。但本人做的实验则是PR提升明显，CP反而降低，十分玄学。而且，在ItemCF-Norm的实验中，Coverage的提升显著，也与书中的结果有些出入"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 附：运行日志（请双击看）\n",
    "\n",
    "1. ItemCF实验\n",
    "Func loadData, run time: 1.357867956161499\n",
    "Func splitData, run time: 1.9750580787658691\n",
    "Experiment 0:\n",
    "Metric: {'Precision': 21.29, 'Recall': 10.22, 'Coverage': 21.3, 'Popularity': 7.167103}\n",
    "Func worker, run time: 105.31731390953064\n",
    "Func splitData, run time: 1.8287019729614258\n",
    "Experiment 1:\n",
    "Metric: {'Precision': 21.45, 'Recall': 10.27, 'Coverage': 21.85, 'Popularity': 7.151314}\n",
    "Func worker, run time: 103.2586419582367\n",
    "Func splitData, run time: 1.8108947277069092\n",
    "Experiment 2:\n",
    "Metric: {'Precision': 21.3, 'Recall': 10.18, 'Coverage': 22.03, 'Popularity': 7.165002}\n",
    "Func worker, run time: 101.99979496002197\n",
    "Func splitData, run time: 1.7960660457611084\n",
    "Experiment 3:\n",
    "Metric: {'Precision': 21.17, 'Recall': 10.18, 'Coverage': 21.34, 'Popularity': 7.178365}\n",
    "Func worker, run time: 102.11498403549194\n",
    "Func splitData, run time: 1.7130441665649414\n",
    "Experiment 4:\n",
    "Metric: {'Precision': 21.21, 'Recall': 10.2, 'Coverage': 21.8, 'Popularity': 7.170794}\n",
    "Func worker, run time: 101.90551114082336\n",
    "Func splitData, run time: 1.8183128833770752\n",
    "Experiment 5:\n",
    "Metric: {'Precision': 21.39, 'Recall': 10.32, 'Coverage': 21.76, 'Popularity': 7.163104}\n",
    "Func worker, run time: 101.97199416160583\n",
    "Func splitData, run time: 1.7958929538726807\n",
    "Experiment 6:\n",
    "Metric: {'Precision': 21.31, 'Recall': 10.25, 'Coverage': 21.9, 'Popularity': 7.161708}\n",
    "Func worker, run time: 101.57879590988159\n",
    "Func splitData, run time: 1.817734956741333\n",
    "Experiment 7:\n",
    "Metric: {'Precision': 21.16, 'Recall': 10.15, 'Coverage': 21.38, 'Popularity': 7.175929}\n",
    "Func worker, run time: 101.03642511367798\n",
    "Average Result (M=8, K=5, N=10): {'Precision': 21.284999999999997, 'Recall': 10.221250000000001, 'Coverage': 21.67, 'Popularity': 7.166664874999999}\n",
    "Func run, run time: 835.2748167514801\n",
    "Func loadData, run time: 1.2348299026489258\n",
    "Func splitData, run time: 1.8201029300689697\n",
    "Experiment 0:\n",
    "Metric: {'Precision': 22.01, 'Recall': 10.57, 'Coverage': 19.35, 'Popularity': 7.248504}\n",
    "Func worker, run time: 104.0655460357666\n",
    "Func splitData, run time: 1.8287677764892578\n",
    "Experiment 1:\n",
    "Metric: {'Precision': 22.12, 'Recall': 10.59, 'Coverage': 18.95, 'Popularity': 7.244242}\n",
    "Func worker, run time: 103.43892693519592\n",
    "Func splitData, run time: 1.804075002670288\n",
    "Experiment 2:\n",
    "Metric: {'Precision': 22.59, 'Recall': 10.8, 'Coverage': 19.19, 'Popularity': 7.245515}\n",
    "Func worker, run time: 103.44988584518433\n",
    "Func splitData, run time: 1.7733349800109863\n",
    "Experiment 3:\n",
    "Metric: {'Precision': 22.02, 'Recall': 10.58, 'Coverage': 19.37, 'Popularity': 7.245227}\n",
    "Func worker, run time: 104.05003190040588\n",
    "Func splitData, run time: 1.8094689846038818\n",
    "Experiment 4:\n",
    "Metric: {'Precision': 22.11, 'Recall': 10.63, 'Coverage': 19.33, 'Popularity': 7.260709}\n",
    "Func worker, run time: 100.68873810768127\n",
    "Func splitData, run time: 1.7294957637786865\n",
    "Experiment 5:\n",
    "Metric: {'Precision': 22.17, 'Recall': 10.69, 'Coverage': 19.02, 'Popularity': 7.251251}\n",
    "Func worker, run time: 101.01811790466309\n",
    "Func splitData, run time: 1.73459792137146\n",
    "Experiment 6:\n",
    "Metric: {'Precision': 22.4, 'Recall': 10.77, 'Coverage': 18.48, 'Popularity': 7.24112}\n",
    "Func worker, run time: 101.37971901893616\n",
    "Func splitData, run time: 1.7321960926055908\n",
    "Experiment 7:\n",
    "Metric: {'Precision': 21.98, 'Recall': 10.54, 'Coverage': 19.18, 'Popularity': 7.259772}\n",
    "Func worker, run time: 101.52781391143799\n",
    "Average Result (M=8, K=10, N=10): {'Precision': 22.174999999999997, 'Recall': 10.646249999999998, 'Coverage': 19.10875, 'Popularity': 7.2495425}\n",
    "Func run, run time: 835.2476677894592\n",
    "Func loadData, run time: 1.2376840114593506\n",
    "Func splitData, run time: 1.7310190200805664\n",
    "Experiment 0:\n",
    "Metric: {'Precision': 22.09, 'Recall': 10.61, 'Coverage': 16.78, 'Popularity': 7.331556}\n",
    "Func worker, run time: 104.41120624542236\n",
    "Func splitData, run time: 1.7812540531158447\n",
    "Experiment 1:\n",
    "Metric: {'Precision': 22.41, 'Recall': 10.73, 'Coverage': 16.87, 'Popularity': 7.327797}\n",
    "Func worker, run time: 104.20949697494507\n",
    "Func splitData, run time: 1.7324512004852295\n",
    "Experiment 2:\n",
    "Metric: {'Precision': 22.5, 'Recall': 10.76, 'Coverage': 16.83, 'Popularity': 7.330741}\n",
    "Func worker, run time: 104.43356919288635\n",
    "Func splitData, run time: 1.7455089092254639\n",
    "Experiment 3:\n",
    "Metric: {'Precision': 21.99, 'Recall': 10.57, 'Coverage': 17.12, 'Popularity': 7.339063}\n",
    "Func worker, run time: 103.83610510826111\n",
    "Func splitData, run time: 1.7279980182647705\n",
    "Experiment 4:\n",
    "Metric: {'Precision': 21.84, 'Recall': 10.5, 'Coverage': 16.99, 'Popularity': 7.340118}\n",
    "Func worker, run time: 104.33192300796509\n",
    "Func splitData, run time: 1.6494619846343994\n",
    "Experiment 5:\n",
    "Metric: {'Precision': 21.86, 'Recall': 10.54, 'Coverage': 16.85, 'Popularity': 7.3356}\n",
    "Func worker, run time: 109.94820308685303\n",
    "Func splitData, run time: 1.9003541469573975\n",
    "Experiment 6:\n",
    "Metric: {'Precision': 22.37, 'Recall': 10.75, 'Coverage': 16.8, 'Popularity': 7.321315}\n",
    "Func worker, run time: 111.54657578468323\n",
    "Func splitData, run time: 1.8000450134277344\n",
    "Experiment 7:\n",
    "Metric: {'Precision': 21.94, 'Recall': 10.52, 'Coverage': 17.12, 'Popularity': 7.351119}\n",
    "Func worker, run time: 108.88186001777649\n",
    "Average Result (M=8, K=20, N=10): {'Precision': 22.125, 'Recall': 10.6225, 'Coverage': 16.919999999999998, 'Popularity': 7.334663624999999}\n",
    "Func run, run time: 867.068473815918\n",
    "Func loadData, run time: 1.2636096477508545\n",
    "Func splitData, run time: 1.806412935256958\n",
    "Experiment 0:\n",
    "Metric: {'Precision': 21.54, 'Recall': 10.34, 'Coverage': 15.47, 'Popularity': 7.389295}\n",
    "Func worker, run time: 114.59086179733276\n",
    "Func splitData, run time: 1.8383910655975342\n",
    "Experiment 1:\n",
    "Metric: {'Precision': 22.08, 'Recall': 10.57, 'Coverage': 15.48, 'Popularity': 7.382177}\n",
    "Func worker, run time: 113.1404218673706\n",
    "Func splitData, run time: 1.806563138961792\n",
    "Experiment 2:\n",
    "Metric: {'Precision': 21.78, 'Recall': 10.41, 'Coverage': 15.07, 'Popularity': 7.382617}\n",
    "Func worker, run time: 113.9739158153534\n",
    "Func splitData, run time: 1.768733263015747\n",
    "Experiment 3:\n",
    "Metric: {'Precision': 21.47, 'Recall': 10.32, 'Coverage': 15.71, 'Popularity': 7.393157}\n",
    "Func worker, run time: 117.33210301399231\n",
    "Func splitData, run time: 1.9012501239776611\n",
    "Experiment 4:\n",
    "Metric: {'Precision': 21.24, 'Recall': 10.21, 'Coverage': 15.74, 'Popularity': 7.397843}\n",
    "Func worker, run time: 120.33364200592041\n",
    "Func splitData, run time: 1.9740369319915771\n",
    "Experiment 5:\n",
    "Metric: {'Precision': 21.12, 'Recall': 10.19, 'Coverage': 15.63, 'Popularity': 7.385106}\n",
    "Func worker, run time: 124.77882289886475\n",
    "Func splitData, run time: 1.9539570808410645\n",
    "Experiment 6:\n",
    "Metric: {'Precision': 21.7, 'Recall': 10.43, 'Coverage': 15.56, 'Popularity': 7.378948}\n",
    "Func worker, run time: 124.54463386535645\n",
    "Func splitData, run time: 1.9221651554107666\n",
    "Experiment 7:\n",
    "Metric: {'Precision': 21.28, 'Recall': 10.21, 'Coverage': 15.23, 'Popularity': 7.404669}\n",
    "Func worker, run time: 124.96897101402283\n",
    "Average Result (M=8, K=40, N=10): {'Precision': 21.526249999999997, 'Recall': 10.335, 'Coverage': 15.48625, 'Popularity': 7.3892265}\n",
    "Func run, run time: 970.096118927002\n",
    "Func loadData, run time: 1.2885360717773438\n",
    "Func splitData, run time: 1.9453051090240479\n",
    "Experiment 0:\n",
    "Metric: {'Precision': 20.71, 'Recall': 9.95, 'Coverage': 13.71, 'Popularity': 7.41184}\n",
    "Func worker, run time: 136.20149898529053\n",
    "Func splitData, run time: 1.9885108470916748\n",
    "Experiment 1:\n",
    "Metric: {'Precision': 21.06, 'Recall': 10.08, 'Coverage': 13.64, 'Popularity': 7.399879}\n",
    "Func worker, run time: 138.96288514137268\n",
    "Func splitData, run time: 1.9737217426300049\n",
    "Experiment 2:\n",
    "Metric: {'Precision': 20.69, 'Recall': 9.89, 'Coverage': 13.18, 'Popularity': 7.405965}\n",
    "Func worker, run time: 140.04792022705078\n",
    "Func splitData, run time: 1.9420268535614014\n",
    "Experiment 3:\n",
    "Metric: {'Precision': 20.69, 'Recall': 9.94, 'Coverage': 13.81, 'Popularity': 7.414836}\n",
    "Func worker, run time: 134.16970086097717\n",
    "Func splitData, run time: 1.8937797546386719\n",
    "Experiment 4:\n",
    "Metric: {'Precision': 20.53, 'Recall': 9.87, 'Coverage': 13.84, 'Popularity': 7.416375}\n",
    "Func worker, run time: 133.87962293624878\n",
    "Func splitData, run time: 1.9022479057312012\n",
    "Experiment 5:\n",
    "Metric: {'Precision': 20.36, 'Recall': 9.82, 'Coverage': 13.57, 'Popularity': 7.411035}\n",
    "Func worker, run time: 134.15448117256165\n",
    "Func splitData, run time: 1.8966238498687744\n",
    "Experiment 6:\n",
    "Metric: {'Precision': 20.79, 'Recall': 9.99, 'Coverage': 13.5, 'Popularity': 7.40158}\n",
    "Func worker, run time: 130.25284504890442\n",
    "Func splitData, run time: 1.8891630172729492\n",
    "Experiment 7:\n",
    "Metric: {'Precision': 20.46, 'Recall': 9.81, 'Coverage': 14.06, 'Popularity': 7.422915}\n",
    "Func worker, run time: 128.92854809761047\n",
    "Average Result (M=8, K=80, N=10): {'Precision': 20.66125, 'Recall': 9.91875, 'Coverage': 13.66375, 'Popularity': 7.410553125}\n",
    "Func run, run time: 1093.511596918106\n",
    "Func loadData, run time: 1.2567250728607178\n",
    "Func splitData, run time: 1.8248507976531982\n",
    "Experiment 0:\n",
    "Metric: {'Precision': 19.56, 'Recall': 9.4, 'Coverage': 11.92, 'Popularity': 7.386144}\n",
    "Func worker, run time: 151.13417983055115\n",
    "Func splitData, run time: 1.8845288753509521\n",
    "Experiment 1:\n",
    "Metric: {'Precision': 19.76, 'Recall': 9.46, 'Coverage': 12.5, 'Popularity': 7.368402}\n",
    "Func worker, run time: 153.7669289112091\n",
    "Func splitData, run time: 2.0910489559173584\n",
    "Experiment 2:\n",
    "Metric: {'Precision': 19.68, 'Recall': 9.41, 'Coverage': 11.96, 'Popularity': 7.379513}\n",
    "Func worker, run time: 164.56706523895264\n",
    "Func splitData, run time: 1.9786031246185303\n",
    "Experiment 3:\n",
    "Metric: {'Precision': 19.4, 'Recall': 9.32, 'Coverage': 12.08, 'Popularity': 7.389774}\n",
    "Func worker, run time: 164.01787090301514\n",
    "Func splitData, run time: 2.0074920654296875\n",
    "Experiment 4:\n",
    "Metric: {'Precision': 19.26, 'Recall': 9.26, 'Coverage': 12.21, 'Popularity': 7.385536}\n",
    "Func worker, run time: 163.91729307174683\n",
    "Func splitData, run time: 1.9719181060791016\n",
    "Experiment 5:\n",
    "Metric: {'Precision': 19.06, 'Recall': 9.19, 'Coverage': 12.22, 'Popularity': 7.379692}\n",
    "Func worker, run time: 165.07782125473022\n",
    "Func splitData, run time: 1.930976152420044\n",
    "Experiment 6:\n",
    "Metric: {'Precision': 19.25, 'Recall': 9.25, 'Coverage': 11.95, 'Popularity': 7.374345}\n",
    "Func worker, run time: 163.38418984413147\n",
    "Func splitData, run time: 1.8265297412872314\n",
    "Experiment 7:\n",
    "Metric: {'Precision': 19.35, 'Recall': 9.28, 'Coverage': 11.87, 'Popularity': 7.401496}\n",
    "Func worker, run time: 156.3625569343567\n",
    "Average Result (M=8, K=160, N=10): {'Precision': 19.415000000000003, 'Recall': 9.32125, 'Coverage': 12.088750000000001, 'Popularity': 7.38311275}\n",
    "Func run, run time: 1299.211760997772\n",
    "\n",
    "2. ItemIUF实验\n",
    "Func loadData, run time: 1.3564789295196533\n",
    "Func splitData, run time: 1.8902332782745361\n",
    "Experiment 0:\n",
    "Metric: {'Precision': 22.51, 'Recall': 10.81, 'Coverage': 17.53, 'Popularity': 7.346247}\n",
    "Func worker, run time: 202.80446100234985\n",
    "Func splitData, run time: 1.8700988292694092\n",
    "Experiment 1:\n",
    "Metric: {'Precision': 22.87, 'Recall': 10.95, 'Coverage': 17.43, 'Popularity': 7.346612}\n",
    "Func worker, run time: 202.73692202568054\n",
    "Func splitData, run time: 1.9114680290222168\n",
    "Experiment 2:\n",
    "Metric: {'Precision': 22.93, 'Recall': 10.96, 'Coverage': 17.86, 'Popularity': 7.353326}\n",
    "Func worker, run time: 202.54596090316772\n",
    "Func splitData, run time: 1.898630142211914\n",
    "Experiment 3:\n",
    "Metric: {'Precision': 22.5, 'Recall': 10.82, 'Coverage': 17.55, 'Popularity': 7.347087}\n",
    "Func worker, run time: 210.07687187194824\n",
    "Func splitData, run time: 2.0206642150878906\n",
    "Experiment 4:\n",
    "Metric: {'Precision': 22.23, 'Recall': 10.69, 'Coverage': 17.62, 'Popularity': 7.355618}\n",
    "Func worker, run time: 194.73034501075745\n",
    "Func splitData, run time: 1.8169701099395752\n",
    "Experiment 5:\n",
    "Metric: {'Precision': 22.73, 'Recall': 10.96, 'Coverage': 17.45, 'Popularity': 7.351502}\n",
    "Func worker, run time: 191.2959520816803\n",
    "Func splitData, run time: 1.7530040740966797\n",
    "Experiment 6:\n",
    "Metric: {'Precision': 22.92, 'Recall': 11.02, 'Coverage': 17.21, 'Popularity': 7.341635}\n",
    "Func worker, run time: 189.27422094345093\n",
    "Func splitData, run time: 1.7417218685150146\n",
    "Experiment 7:\n",
    "Metric: {'Precision': 22.42, 'Recall': 10.75, 'Coverage': 17.72, 'Popularity': 7.360763}\n",
    "Func worker, run time: 196.7241768836975\n",
    "Average Result (M=8, K=10, N=10): {'Precision': 22.63875, 'Recall': 10.87, 'Coverage': 17.54625, 'Popularity': 7.350348749999999}\n",
    "Func run, run time: 1606.6134660243988\n",
    "\n",
    "3. ItemCF-Norm实验\n",
    "Func loadData, run time: 1.2446231842041016\n",
    "Func splitData, run time: 1.8000209331512451\n",
    "Experiment 0:\n",
    "Metric: {'Precision': 22.43, 'Recall': 10.77, 'Coverage': 37.4, 'Popularity': 6.997795}\n",
    "Func worker, run time: 106.30902194976807\n",
    "Func splitData, run time: 1.8364269733428955\n",
    "Experiment 1:\n",
    "Metric: {'Precision': 22.64, 'Recall': 10.84, 'Coverage': 37.74, 'Popularity': 6.993843}\n",
    "Func worker, run time: 105.63388681411743\n",
    "Func splitData, run time: 1.820976972579956\n",
    "Experiment 2:\n",
    "Metric: {'Precision': 23.06, 'Recall': 11.03, 'Coverage': 37.05, 'Popularity': 6.994036}\n",
    "Func worker, run time: 108.06170320510864\n",
    "Func splitData, run time: 1.9166691303253174\n",
    "Experiment 3:\n",
    "Metric: {'Precision': 22.52, 'Recall': 10.82, 'Coverage': 38.16, 'Popularity': 7.003088}\n",
    "Func worker, run time: 112.67198371887207\n",
    "Func splitData, run time: 1.895146131515503\n",
    "Experiment 4:\n",
    "Metric: {'Precision': 22.56, 'Recall': 10.85, 'Coverage': 38.82, 'Popularity': 7.001239}\n",
    "Func worker, run time: 107.44453597068787\n",
    "Func splitData, run time: 1.7972638607025146\n",
    "Experiment 5:\n",
    "Metric: {'Precision': 22.74, 'Recall': 10.97, 'Coverage': 37.12, 'Popularity': 7.007333}\n",
    "Func worker, run time: 106.20418381690979\n",
    "Func splitData, run time: 1.7266900539398193\n",
    "Experiment 6:\n",
    "Metric: {'Precision': 22.82, 'Recall': 10.97, 'Coverage': 37.7, 'Popularity': 6.989135}\n",
    "Func worker, run time: 106.62335729598999\n",
    "Func splitData, run time: 1.8284211158752441\n",
    "Experiment 7:\n",
    "Metric: {'Precision': 22.49, 'Recall': 10.79, 'Coverage': 37.47, 'Popularity': 7.009879}\n",
    "Func worker, run time: 106.70008587837219\n",
    "Average Result (M=8, K=10, N=10): {'Precision': 22.6575, 'Recall': 10.879999999999999, 'Coverage': 37.682500000000005, 'Popularity': 6.9995435}\n",
    "Func run, run time: 875.6982419490814"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
